package com.wuyangnju.lj.callcenter.run;

/******************************************************************\
 * File:           SimGGNG.java for Queueing System
 * Language:       Java 1.6
 * Copyright:      Jiheng Zhang, 
 *                 Hong Kong University of Science and Technology
 * Date:           March 4, 2011
 \******************************************************************/

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import umontreal.iro.lecuyer.randvar.ErlangGen;
import umontreal.iro.lecuyer.randvar.ExponentialGen;
import umontreal.iro.lecuyer.randvar.LognormalGen;
import umontreal.iro.lecuyer.randvar.RandomVariateGen;
import umontreal.iro.lecuyer.rng.MRG32k3a;
import umontreal.iro.lecuyer.util.Chrono;

import com.wuyangnju.lj.callcenter.model.CallCenter;
import com.wuyangnju.lj.callcenter.util.HeadCountSnapshot;
import com.wuyangnju.lj.callcenter.util.LognormalConvert;

public class SimCallCenter {
	private static final Log log = LogFactory.getLog(SimCallCenter.class);

	public static void main(String[] args) {

		// ---------------------- begin parameter setting ----------------------
		double mu, lambda, simTime;
		// double theta;
		int N, round;

		mu = 1;
		N = 100;
		// double k = 6;
		// lambda = 100*k/(k-1.);
		lambda = 102;
		// theta = 1;

		// simTime = 2E4;
		// round = 8;

		simTime = 1E1;
		round = 2;

		long eventLimit = 1000000;

		// setting random variable generator
		// double var = 4;
		// LognormalConvert lncSer = new LognormalConvert(1./mu, var, true);
		// LognormalConvert lncReg = new LognormalConvert(1./theta, var, true);

		RandomVariateGen genArr;
		RandomVariateGen[] genServ = new RandomVariateGen[3];
		RandomVariateGen[] genReg = new RandomVariateGen[6];

		genArr = new ExponentialGen(new MRG32k3a(), lambda);

		genServ[0] = new ExponentialGen(new MRG32k3a(), mu);
		// genServ[1] = new ErlangGen (new MRG32k3a(), 2, mu*2.);
		// genServ[2] = new LognormalGen (new MRG32k3a(), lncSer.mu,
		// lncSer.sigma);

		// genReg[0] = new ExponentialGen (new MRG32k3a(), theta);
		genReg[0] = new ErlangGen(new MRG32k3a(), 2, 2. / .25);
		genReg[1] = new ErlangGen(new MRG32k3a(), 2, 2. / 1);
		genReg[2] = new ErlangGen(new MRG32k3a(), 2, 2. / 4);
		LognormalConvert lncReg = new LognormalConvert(1 / mu, 4, true);
		genReg[3] = new LognormalGen(new MRG32k3a(), lncReg.mu, lncReg.sigma);
		lncReg = new LognormalConvert(4, 4, true);
		genReg[4] = new LognormalGen(new MRG32k3a(), lncReg.mu, lncReg.sigma);
		lncReg = new LognormalConvert(4, 64, true);
		genReg[5] = new LognormalGen(new MRG32k3a(), lncReg.mu, lncReg.sigma);

		// ---------------------- end parameter setting ----------------------

		Chrono timer = new Chrono();
		// for (int is = 0; is < 1; is++) {
		// for (int ir = 0; ir <= 5; ir++) {
		int is = 0, ir = 0;
		genArr = new ExponentialGen(new MRG32k3a(), lambda);
		// CallCenter queue = new CallCenter(N, genArr,
		// genServ[is],genReg[ir]);
		int[] NA = { N, N };
		double[] pA = { 0, 0.5 };
		RandomVariateGen[] genArrA = { genArr, genArr };
		RandomVariateGen[] genServA = { genServ[is], genServ[is] };
		RandomVariateGen[] genRegA = { genReg[ir], genReg[ir] };

		CallCenter queue = new CallCenter(NA, pA, genArrA, genServA, genRegA,
				"_" + is + "_" + ir, eventLimit);

		queue.simulate(simTime, round);

		System.out.println("Service Distribution:" + genServ[is].toString());
		System.out.println("Renege Distribution:" + genReg[ir].toString());

		for (int i = 0; i < 2; i++) {
			for (int j = 0; j < 4; j++) {
				if (j == 0 || j == 2)
					System.out.println(queue.getHeadCount()[i][j]
							.reportAndCIStudent(0.95, 5));
			}
			for (int j = 0; j < 1; j++) {
				System.out.println(queue.getTimeAverage()[i][j]
						.reportAndCIStudent(0.95, 2));
			}
		}
		drawPic(queue.getSnapshots(), "_" + is + "_" + ir);
		// }
		// }

		System.out.println("Total CPU time:      " + timer.format() + "\n");
	}

	public static void drawPic(List<HeadCountSnapshot> snapshots, String simId) {

		try {

			// StringBuilder xtic = new StringBuilder("\"0\" 0");
			// for (int i = 0; i < data.size(); i++) {
			// xtic.append(", \"" + data.get(i).t + "\" " + data.get(i).t);
			// }

			File dataFile = new File("callcenter" + simId + ".dat");
			if (dataFile.exists()) {
				dataFile.delete();
			}
			dataFile.createNewFile();
			PrintWriter pwdata = new PrintWriter(dataFile);
			for (HeadCountSnapshot snapshot : snapshots) {
				pwdata.println(snapshot.t + ", " + snapshot.b[0] + ", "
						+ snapshot.b[1] + ", " + snapshot.s[0] + ", "
						+ snapshot.s[1] + ", " + snapshot.s0[0] + ", "
						+ snapshot.s0[1]);
			}
			pwdata.close();

			// gnuplot file

			File gnuplotFile = new File("callcenter" + simId + ".gnuplot");
			if (gnuplotFile.exists()) {
				gnuplotFile.delete();
			}
			gnuplotFile.createNewFile();

			String terminal = "png";
			String picFileName = "callcenter" + simId + "." + terminal;
			String title = "call center";
			String xLabel = "time";
			String yLabel = "head count";
			String pointtype = "0";
			String linespoints = "1";
			String datFile = "callcenter" + simId + ".dat";

			PrintWriter pw = new PrintWriter(gnuplotFile);
			pw.println("set datafile separator \",\"");
			pw.println("set terminal " + terminal);
			pw.println("set output \"" + picFileName + "\"");
			pw.println("set datafile separator \",\"");
			pw.println("set title \"" + title + "\"");
			pw.println("set xlabel \"" + xLabel + "\"");
			pw.println("set ylabel \"" + yLabel + "\"");
			// pw.println("set xtic (" + xtic + ")");
			pw.println("plot \""
					+ datFile
					+ "\" using 1:2 title \"b0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:3 title \"b1\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:4 title \"s0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:5 title \"s1\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:6 title \"s0_from_b0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:7 title \"s0_from_b1\" with linespoints pointtype "
					+ pointtype + " linewidth " + linespoints);
			pw.close();
			// gnuplot file end

			//
			Process p = Runtime.getRuntime().exec("gnuplot");

			PrintWriter pw3 = new PrintWriter(p.getOutputStream());
			pw3.println("set datafile separator \",\"");
			pw3.println("set terminal " + terminal);
			pw3.println("set output \"" + picFileName + "\"");
			pw3.println("set datafile separator \",\"");
			pw3.println("set title \"" + title + "\"");
			pw3.println("set xlabel \"" + xLabel + "\"");
			pw3.println("set ylabel \"" + yLabel + "\"");
			// pw3.println("set xtic (" + xtic + ")");
			pw3.println("plot \""
					+ datFile
					+ "\" using 1:2 title \"b0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:3 title \"b1\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:4 title \"s0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:5 title \"s1\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:6 title \"s0_from_b0\" with linespoints pointtype "
					+ pointtype
					+ " linewidth "
					+ linespoints
					+ ", \""
					+ datFile
					+ "\" using 1:7 title \"s0_from_b1\" with linespoints pointtype "
					+ pointtype + " linewidth " + linespoints);
			pw3.close();

			BufferedReader br = new BufferedReader(new InputStreamReader(
					p.getErrorStream()));
			String line;
			while ((line = br.readLine()) != null) {
				System.out.println(line);
			}

			BufferedReader br2 = new BufferedReader(new InputStreamReader(
					p.getInputStream()));
			while ((line = br2.readLine()) != null) {
				System.out.println(line);
			}

			System.out.println(p.exitValue());
			//
		} catch (IOException e) {
			log.error(e, e);
		}
	}
}
